package com.policyCloud.policyGateway.filter;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private String stringValue=null;
    private static Joiner joiner = Joiner.on("");

    @Override
    public int getOrder() {
        return -2;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String cookieID=exchange.getRequest().getHeaders().getFirst("cookie");
        if(StringUtils.isEmpty(cookieID)){
            WebSession session = exchange.getSession().block();
            String JSESSIONID = session.getId();
            String cook = new HttpCookie("ZCK-JSESSIONID", JSESSIONID).toString();
            ServerHttpRequest newRequest = exchange.getRequest().mutate().headers((httpHeaders) -> {
                httpHeaders.set("Cookie", cook);
            }).build();
            exchange.mutate().request(newRequest).build();
        }
        request = exchange.getRequest();
        if(request.getPath().toString().equals("/login/oauth/token")){
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                            List<String> list = Lists.newArrayList();

                            dataBuffers.forEach(dataBuffer -> {
                                byte[] content = new byte[dataBuffer.readableByteCount()];
                                dataBuffer.read(content);
                                DataBufferUtils.release(dataBuffer);

                                list.add(new String(content,  StandardCharsets.UTF_8));
                            });
                            String s = joiner.join(list);
                            stringValue =s;
                            String cookieID=exchange.getRequest().getHeaders().getFirst("cookie");
                            cookieID = cookieID.replace("=",":");
                            stringRedisTemplate.opsForValue().set(cookieID, stringValue,60*60*6, TimeUnit.SECONDS);
                            return bufferFactory().wrap(s.getBytes());
                        }));
                    }
                    return super.writeWith(body);
                }
            };
            String[] sli =exchange.getRequest().getHeaders().getFirst("cookie").split("=");
            decoratedResponse.getHeaders().add("ZCK-JSESSIONID",  sli[1]);
//            decoratedResponse.addCookie(ResponseCookie.from("JSESSIONID",  sli[1])
//                    .maxAge(Duration.between(LocalDateTime.now(), LocalDateTime.now().minusHours(6)).getSeconds())
//                    .domain("http://localhost:8866")
//                    .path("/")
//                    .build());
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        }

        return chain.filter(exchange);
    }
}